<template>
  <div class="common-uploader" :class="{ 'flex': multiple }">
    <div v-if="imgUrl" class="img_wrapper" :style="{ 'width': wrapperWidth, 'height': wrapperHeight }">
      <img v-if="imgUrl" :src="$globalObj.imgBaseUrl + imgUrl" class="w-100 h-100">
      <el-image-viewer zIndex="5999" v-if="showViewer" :on-close="closeViewer" :url-list="[$globalObj.imgBaseUrl + imgUrl]" />
      <p class="mask_tool">
        <span class="flex-1 text-center pointer" @click.stop="showViewer = true">查看</span>
        <el-divider v-if="!hideDelete" direction="vertical"></el-divider>
        <span v-if="!hideDelete" class="flex-1 text-center pointer" @click.stop="delImg">删除</span>
      </p>
    </div>
    <div class="flex flex-wrap mul_list" v-if="multiple">
      <template v-if="fileList.length > 0">
        <el-image-viewer zIndex="5999" v-if="showViewer" :on-close="closeViewer" :url-list="[$globalObj.imgBaseUrl + showUrl]" />
        <template v-if="!sort">
          <div v-for="(item, index) in sortList" :key="item" class="inline-block img_wrapper"
            :style="{ 'width': wrapperWidth, 'height': wrapperHeight }">
            <img v-if="item" :src="$globalObj.imgBaseUrl + item" class="w-100 h-100">
            <!-- <el-image-viewer
              v-if="showViewer"
              :on-close="closeViewer"
              :url-list="[$globalObj.imgBaseUrl+item]"
            /> -->
            <p class="mask_tool">
              <span class="flex-1 text-center pointer" @click.stop="previewImg(item)">查看</span>
              <el-divider v-if="!hideDelete" direction="vertical"></el-divider>
              <span v-if="!hideDelete" class="flex-1 text-center pointer" @click.stop="delImg(index)">删除</span>
            </p>
          </div>
        </template>
        <vuedraggable v-else v-model="sortList" class="draggable-container">
          <transition-group>
            <div v-for="(item, index) in sortList" :key="item" class="inline-block img_wrapper"
              :style="{ 'width': wrapperWidth, 'height': wrapperHeight }">
              <img v-if="item" :src="$globalObj.imgBaseUrl + item" class="w-100 h-100">
              <!-- <el-image-viewer
                v-if="showViewer"
                :on-close="closeViewer"
                :url-list="[$globalObj.imgBaseUrl+item]"
              /> -->
              <p class="mask_tool">
                <span class="flex-1 text-center pointer" @click.stop="previewImg(item)">查看</span>
                <el-divider v-if="!hideDelete" direction="vertical"></el-divider>
                <span v-if="!hideDelete" class="flex-1 text-center pointer" @click.stop="delImg(index)">删除</span>
              </p>
            </div>
          </transition-group>
        </vuedraggable>
      </template>
      <!-- :multiple="multiple" -->
      <el-upload v-if="fileList.length < maxNum" ref="upload" action="string" :accept="accept ? accept : 'image/*'"
        :show-file-list="false" :http-request="httpRequest" :multiple="isShow" :before-upload="beforeUpload">
        <el-button v-if="showType === 'button'" size="small" type="primary">点击上传</el-button>
        <div v-if="showType === 'photo'" :style="{ 'width': photoWidth + 'px', 'height': photoHeight + 'px' }"
          class="flex flex-column align-center justify-center photo_wrapper">
          <i class="el-icon-plus"></i>
          <span>上传图片</span>
        </div>
        <div v-if="tip" slot="tip" class="el-upload__tip">{{ tip }}<br v-if="subTip" />{{ subTip }}</div>
      </el-upload>
    </div>
    <el-upload v-if="!multiple && !imgUrl" ref="upload" action="string" :accept="accept ? accept : 'image/*'"
      :show-file-list="false" :http-request="httpRequest" :before-upload="beforeUpload">
      <el-button v-if="showType === 'button'" size="small" type="primary">点击上传</el-button>
      <div v-if="showType === 'photo'" :style="{ 'width': photoWidth + 'px', 'height': photoHeight + 'px' }"
        class="flex flex-column align-center justify-center photo_wrapper">
        <i class="el-icon-plus"></i>
        <span>上传图片</span>
      </div>
      <div v-if="tip" slot="tip" class="el-upload__tip">{{ tip }}<br v-if="subTip" />{{ subTip }}</div>
    </el-upload>
    <!-- 
    <el-dialog :width="dialogWidth" title="图片剪裁" :visible.sync="dialogVisible" append-to-body>
      <div class="m-auto cropper" :style="{ 'width': cropperWidth, 'height': cropperHeight }">
        <vueCropper ref="cropper" :img="option.img" :outputType="outputType" :outputSize="option.outputSize"
          :info="option.info" :canScale="option.canScale" :autoCrop="option.autoCrop" :autoCropWidth="autoCropWidth"
          :autoCropHeight="autoCropHeight" :fixed="fixScale" :fixedBox="fixedBox" :fixedNumber="option.fixedNumber"
          :enlarge="enlarge"></vueCropper>
-->
    <el-dialog :width="dialogWidth" title="图片上传" :visible.sync="dialogVisible" append-to-body>
      <div class="m-auto cropper" :style="{ 'width': cropperWidth, 'height': cropperHeight }">
        <vueCropper ref="cropper" :img="option.img" :outputType="outputType" :outputSize="option.outputSize"
          :info="option.info" :canScale="option.canScale" :autoCrop="option.autoCrop" :autoCropWidth="autoCropWidth"
          :autoCropHeight="autoCropHeight" :fixed="fixScale" :fixedBox="fixedBox" :fixedNumber="option.fixedNumber"
          :enlarge="enlarge"></vueCropper>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button size="small" type="primary" @click="cancelCrop">上传</el-button>
        <!-- <el-button
          size="small"
          type="primary"
          @click="finish"
          :loading="loading"
        >裁剪</el-button> -->
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { upload } from "@/api/index";
import { VueCropper } from 'vue-cropper';
import ElImageViewer from 'element-ui/packages/image/src/image-viewer';
import vuedraggable from 'vuedraggable'
export default {
  components: { VueCropper, ElImageViewer, vuedraggable },
  props: {
    dialogWidth: {
      type: String,
      default: "400px"
    },
    showType: {
      type: String,
      default: "button"
    },
    accept: {
      type: String
    },
    tip: {
      type: String,
      default: ""
    },
    subTip: {
      type: String,
      default: ""
    },
    fileSize: {
      type: String,
      default: "2M"
    },
    imgWidth: {
      type: Number
    },
    imgHeight: {
      type: Number
    },
    wrapperWidth: {
      type: String,
      default: "auto"
    },
    wrapperHeight: {
      type: String
    },
    alwaysCrop: {
      type: Boolean,
      default: false
    },
    fixedBox: {
      type: Boolean,
      default: true
    },
    autoCropWidth: {
      type: Number
    },
    autoCropHeight: {
      type: Number
    },
    fixScale: {
      type: Boolean,
      default: false
    },
    cropperWidth: {
      type: String,
      default: '100%'
    },
    cropperHeight: {
      type: String
    },
    photoWidth: {
      type: Number,
      default: 95
    },
    photoHeight: {
      type: Number,
      default: 95
    },
    initVal: {},
    enlarge: {
      type: Number,
      default: 1
    },
    minWidth: {
      type: Number
    },
    minHeight: {
      type: Number
    },
    multiple: {
      type: Boolean,
      default: false
    },
    maxNum: {
      type: Number,
      default: 10
    },
    sort: {
      type: Boolean,
      default: false
    },
    isSquare: {
      type: Boolean,
      default: false
    },
    hideDelete: {
      type: Boolean,
      default: false
    },
    params: {
      type: Number,
      default: 1
    },
    type: {
      type: String,
      default: 'meal'
    },
    isShow: {
      type: Boolean,
      default: true
    }
  },
  computed: {
    outputType() {
      if ((this.accept && this.accept.indexOf('png') > -1) || this.alwaysCrop) {
        return 'png'
      } else {
        return 'jpeg'
      }
    },
    imgUrl() {
      console.log(this.multiple ? "" : (this.initVal ? this.initVal : ""));
      return this.multiple ? "" : (this.initVal ? this.initVal : "");

    },
    fileList() {
      return this.multiple ? (this.initVal ? this.initVal : []) : [];
    },
  },
  data() {
    return {
      dialogVisible: false,
      // 裁剪组件的基础配置option
      option: {
        img: '', // 裁剪图片的地址
        info: true, // 裁剪框的大小信息
        outputSize: 0.8, // 裁剪生成图片的质量
        canScale: false, // 图片是否允许滚轮缩放
        autoCrop: false, // 是否默认生成截图框
        full: false, // 是否输出原图比例的截图
        canMoveBox: false, // 截图框能否拖动
        original: true, // 上传图片按照原始比例渲染
        infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
        canMove: true,
      },
      loading: false,
      fileInfo: null,
      showViewer: false,
      sortList: [],
      showUrl: '',
    }
  },
  mounted() {
    // this.$nextTick(() => {
    //   if (this.multiple) {
    //     this.sortList = [...this.fileList];
    //   }
    // })
  },
  updated() {
    this.sortList = this.initVal
  },
  // watch: {
  //   sortList: {
  //     handler(val) {
  //         if (this.sort) {
  //         this.$emit("setVal", [val, this.params], 'sort');
  //     }
  //     deep: true
  //   }
  // },
  // },
  methods: {
    previewImg(url) {
      this.showUrl = url;
      this.$nextTick(() => {
        this.showViewer = true;
      })
    },
    // 删除
    delImg(index) {
      if (this.multiple) {
        this.$emit("setVal", [index, this.params], 'del');
      } else {
        if (this.type === 'meal') {
          this.$emit("setVal", [index, this.params]);
        }
        this.$emit("setVal", "");

      }
    },
    // 关闭预览
    closeViewer() {
      this.showViewer = false;
    },
    // 直接上传
    cancelCrop() {
      if (this.imgWidth || this.imgHeight || this.minWidth || this.minHeight || this.isSquare) {
        this.sizeCheck(this.fileInfo).then(res => {
          if (res) {
            let fd = new FormData();
            fd.append("file", this.fileInfo);
            upload(fd).then(res => {
              if (this.multiple) {
                this.$emit("setVal", [res.image, this.params], 'add')
              } else {
                this.$emit("setVal", [res.image, this.params])
              }
              this.dialogVisible = false;
            })
          }
        });
      } else {
        let fd = new FormData();
        fd.append("file", this.fileInfo);
        upload(fd).then(res => {
          if (this.multiple) {
            this.$emit("setVal", [res.image, this.params], 'add');
          } else {
            this.$emit("setVal", [res.image, this.params]);
          }
          this.dialogVisible = false;
        });
      }
    },
    // 裁剪
    finish() {
      this.loading = true;
      this.$refs.cropper.getCropBlob((data) => {
        let file = new window.File([data], this.fileInfo.name, { type: data.type });
        if (this.imgWidth || this.imgHeight || this.minWidth || this.minHeight || this.isSquare) {
          this.sizeCheck(file).then(res => {
            if (res) {
              let fd = new FormData();
              fd.append("file", file);
              upload(fd).then(res => {
                this.loading = false;
                if (this.multiple) {
                  this.$emit("setVal", [res.image, this.params], 'add');
                } else {
                  this.$emit("setVal", [res.image, this.params]);
                }
                this.dialogVisible = false;
              }).catch(error => {
                this.loading = false;
              });
            }
          }).catch(() => {
            this.loading = false;
          });
        } else {
          let fd = new FormData();
          fd.append("file", file);
          upload(fd).then(res => {
            this.loading = false;
            if (this.multiple) {
              this.$emit("setVal", [res.image, this.params], 'add');
            } else {
              this.$emit("setVal", [res.image, this.params]);
            }
            this.dialogVisible = false;
          }).catch(error => {
            this.loading = false;
          });
        }
      })
    },
    async sizeCheck(file) {
      let that = this;
      let flag, minWValid, minHValid, imgWValid, imgHValid;
      const isSize = await new Promise(function (resolve, reject) {
        let _URL = window.URL || window.webkitURL;
        let img = new Image();
        img.onload = function () {
          minWValid = that.minWidth ? img.width >= that.minWidth : true;
          minHValid = that.minHeight ? img.height >= that.minHeight : true;
          imgWValid = that.imgWidth ? img.width == that.imgWidth : true;
          imgHValid = that.imgHeight ? img.height == that.imgHeight : true;
          flag = that.isSquare ? img.width === img.height : true;
          minWValid && minHValid && imgWValid && imgHValid && flag ? resolve() : reject();
        }
        img.src = _URL.createObjectURL(file)
      }).then(() => {
        return file
      }, () => {
        if (!flag) {
          that.$message.error('图片要求为正方形！');
        } else if (!minWValid) {
          that.$message.error('图片尺寸要求宽度最小为' + that.minWidth + 'px！');
        } else if (!minHValid) {
          that.$message.error('图片尺寸要求高度最小为' + that.minHeight + 'px！');
        } else if (!imgWValid) {
          that.$message.error('图片尺寸要求宽度为' + that.imgWidth + 'px！');
        } else if (!imgHValid) {
          that.$message.error('图片尺寸要求高度为' + that.imgHeight + 'px！');
        }
        return Promise.reject()
      })
      return isSize
    },
    // 上传前对文件的大小进行判断
    beforeUpload(file) {
      this.fileInfo = file
      const isFileSize = true, hasAccept = true, isSize = true
      // if (this.fileSize) {
      //   const size = parseInt(this.fileSize.slice(0, -1));
      //   if (this.fileSize.indexOf('K') > -1) {
      //     isFileSize = file.size / 1024 < size;
      //   }
      //   if (this.fileSize.indexOf('M') > -1) {
      //     isFileSize = file.size / 1024 / 1024 < size;
      //   }
      //   if (!isFileSize) {
      //     this.$message({
      //       message: "上传文件大小不能超过" + this.fileSize,
      //       type: "error"
      //     });
      //     return false;
      //   }
      // }
      if (this.accept) {
        const fileExt = file.name.substring(file.name.lastIndexOf('.'))
        const list = this.accept.split(',')
        hasAccept = list.find(item => item === fileExt) ? true : false
        if (!hasAccept) {
          this.$message({
            message: '上传文件类型必须为' + this.accept,
            type: 'error'
          })
          return false
        }
      }
      if (this.alwaysCrop) {
        this.option.img = URL.createObjectURL(file)
        this.dialogVisible = true
        return false
      }
      if (this.imgWidth || this.imgHeight || this.minWidth || this.minHeight || this.isSquare) {
        isSize = this.sizeCheck(file)
      }
      return hasAccept && isSize
      // return isFileSize && hasAccept && isSize;
    },
    // 覆盖默认上传行为
    httpRequest(params) {
      const fd = new FormData()
      fd.append('file', params.file)
      upload(fd).then(res => {
        if (this.multiple) {
          this.$emit('setVal', [res.image, this.params], 'add')
        } else {
          // this.$emit('setVal', [res.image, this.params])
          this.$emit('setVal', [res.image])
        }
      })
    }
  }
}
</script>

<style lang="scss">
.common-uploader {
  .el-upload__tip {
    margin-top: 0;
    color: #bbbbbb;
  }

  .img_wrapper {
    position: relative;
    border: 1px solid #e6e6e6;

    &:hover .mask_tool {
      display: flex;
      align-items: center;
    }
  }

  .mask_tool {
    display: none;
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 3;
    height: 30px;
    color: #ffffff;
    background: rgba(0, 0, 0, 0.75);

    .el-divider {
      height: 18px;
      margin: 0;
    }
  }

  .photo_wrapper {
    background: #ffffff;
    border: 1px solid #eeeeee;
    color: #999999;

    i {
      font-size: 30px;
      color: #cccccc;
    }

    span {
      line-height: 30px;
    }
  }

  .mul_list .img_wrapper {
    margin-right: 10px;
    margin-bottom: 10px;
  }
}

// .el-image-viewer__wrapper {
//   z-index: 2090 !important;
// }
</style>
